package ba01_Before;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author HLF
 * @version V1.0
 * @package ba01
 * @date 2021/10/17 10:19
 * @Aspect 是aspectj框架的注解，表示当前类是切面类
 * 切面类：用来给业务方法增加功能的类，在这个类中有增加切面功能的代码
 * 位置：在切面类定义的上面
 */
@Aspect
@Component//创建切面类对象
public class MyAspect {

    /**
     * @Before 前置通知，表示在执行目标方法之前执行
     * 属性：value，为切入点表达式，表示执行切面的位置
     * 位置：方法定义的上面
     *
     *
     * 定义方法，方法是实现切面功能的。
     * 方法的定义要求：
     *      1.公共方法 public
     *      2.方法没有返回值
     *      3.方法名称自定义
     *      4.方法可以有参数，也可以没有参数。如果有参数，参数不是自定义的，有几个参数类型可以使用。
     *
     *  特点：
     *  1.在目标方法之前先执行的
     *  2.不会改变目标方法的执行结果
     *  3.不会影响目标方法的执行。
     *
     */

    /**
     * 指定通知方法(myBefore方法)中的参数 ： JoinPoint
     * JoinPoint:业务方法，要加入切面功能的业务方法(例如doSome方法)
     *    作用是：可以在通知方法中获取方法执行时的信息， 例如方法名称，方法的实参。
     *    如果你的切面功能中需要用到方法的信息，就加入JoinPoint.
     *    这个JoinPoint参数的值是由框架赋予，必须是第一个位置的参数
     */
    //value="切入点表达式"
    @Before(value = "execution(public void ba01_Before.SomeServiceImpl.doSome(String,Integer))")//完整写法
    //@Before(value = "execution(void *..SomeServiceImpl.doSome(String,Integer))")
    //@Before(value = "execution(* *..SomeServiceImpl.*(..))")
    //@Before(value = "execution(* ba01.*.*(..))")
    //@Before(value = "execution(* *ba01.*ServiceImpl.*(..))")
    //@Before(value = "execution(* do*(..))")
    public void myBefore(JoinPoint joinPoint) {
        //获取方法的完整定义
        System.out.println("方法的签名(定义)"+joinPoint.getSignature());
        System.out.println("方法的名称"+joinPoint.getSignature().getName());
        //获取方法的实参
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            System.out.println("方法的实参："+arg);//按位置输出args[0]是name  args[1]是age
        }

        //切面代码的功能，例如日志，事务
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss SSS");
        String nowTime = sdf.format(new Date());
        System.out.println("输出日志:" + nowTime);
    }
}
